#ifndef __LIBC_IPC_H
    #define __LIBC_IPC_H

    #ifdef __cplusplus
    extern "C"
    {
    #endif

    #include <types.h>

    #define FIRST_CALL_CODE (0x00000001)
    #define LAST_CALL_CODE (0x000fffff)

    #define LPC_MSG_USE_MALLOC 1
    #define LPC_PARCEL_ARG_NUM 8
    #define LPC_PARCEL_BUFF_SIZE 256

    typedef struct _lpc_parcel _lpc_parcel_t;
    typedef _lpc_parcel_t *lpc_parcel_t;

    typedef bool (*lpc_handler_t)(uint32_t, lpc_parcel_t, lpc_parcel_t);
    typedef bool (*lpc_remote_handler_t)(lpc_parcel_t, lpc_parcel_t);

    typedef enum
    {
        LPC_PARCEL_ARG_UNKNOW = 0,
        LPC_PARCEL_ARG_CHAR,
        LPC_PARCEL_ARG_SHORT,
        LPC_PARCEL_ARG_INT,
        LPC_PARCEL_ARG_LONG,
        LPC_PARCEL_ARG_FLOAT,
        LPC_PARCEL_ARG_DOUBLE,
        LPC_PARCEL_ARG_STRING,
        LPC_PARCEL_ARG_SEQUEUECE,
    } lpc_parcel_arg_type;

    typedef struct lpc_parcel_header
    {
        uint32_t args[LPC_PARCEL_ARG_NUM];    //args value
        uint16_t arglen[LPC_PARCEL_ARG_NUM];  //args len
        uint16_t argtype[LPC_PARCEL_ARG_NUM]; //args type
        uint32_t argused;                     //args used flags
        uint32_t size;                        //size
    } lpc_parcel_header_t;

    typedef struct _lpc_parcel
    {
        lpc_parcel_header_t header;
        uint32_t code; //call code
        uint8_t data[1];
    } _lpc_parcel_t;

    #define LPC_ID_TEST PORT_COMM_TEST
    #define LPC_ID_NET PORT_COMM_NET
    #define LPC_ID_GRAPH PORT_COMM_GRAPH

    lpc_parcel_t lpc_parcel_get();
    int lpc_parcel_put(lpc_parcel_t parcel);
    void lpc_parcel_dump_args(lpc_parcel_t parcel);
    int lpc_parcel_write_string(lpc_parcel_t parcel, char *str);
    int lpc_parcel_write_sequence(lpc_parcel_t parcel, void *buff, size_t len);
    int lpc_parcel_write_int(lpc_parcel_t parcel, uint32_t num);
    int lpc_parcel_write_short(lpc_parcel_t parcel, uint16_t num);
    int lpc_parcel_write_long(lpc_parcel_t parcel, uint64_t num);
    int lpc_parcel_write_char(lpc_parcel_t parcel, uint8_t ch);
    int lpc_parcel_read_char(lpc_parcel_t parcel, uint8_t *ch);
    int lpc_parcel_read_int(lpc_parcel_t parcel, uint32_t *num);
    int lpc_parcel_read_string(lpc_parcel_t parcel, char **str);
    int lpc_parcel_read_sequence_buff(lpc_parcel_t parcel, void **buff, size_t *len);
    int lpc_do_echo(uint32_t port, lpc_handler_t func);
    int lpc_echo(uint32_t port, lpc_handler_t func);
    int lpc_echo_group(uint32_t port, lpc_handler_t func);
    int lpc_call(uint32_t port, uint32_t code, lpc_parcel_t data, lpc_parcel_t reply);

    #ifdef __cplusplus
    }
    #endif
#endif